/**
 * Copyright (c) 2017-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 * @format
 */

import type {NuclideUri} from 'nuclide-commons/nuclideUri';

export const THRIFT_SERVICE_TAG = 'thrift-services';

export type ThriftServiceConfig = {
  // service name
  name: string,
  // uri of the thrift server
  remoteUri: NuclideUri,
  // path to run the thrift server
  remoteCommand: string,
  // args sent in execution of command above
  remoteCommandArgs: Array<string>,
  // server connection options
  remoteConnection: RemoteConnectionType,
  // thrift transport used to communicate
  thriftTransport: 'framed' | 'buffered',
  // thrift protocol used to communicate
  thriftProtocol: 'binary' | 'compact' | 'json',
  // service generated by Thrift
  thriftService: mixed,
  // kill old server process when starting server for the first time.
  killOldThriftServerProcess: boolean,
};

// a subset of attributes from ThriftServiceConfig
export type ThriftServerConfig = {
  // thrift service name
  name: string,
  // remote command to manage thrift server
  remoteCommand: string,
  // remote command args sent along with the command above
  remoteCommandArgs: Array<string>,
  // server connection options
  remoteConnection: RemoteConnectionType,
  // kill old server process when starting server for the first time.
  killOldThriftServerProcess: boolean,
};

type RemoteConnectionType =
  | {
      type: 'tcp',
      port: number,
    }
  | {
      type: 'ipcSocket',
      path: string,
    };

export type ThriftMessagePayload = Request | SuccessResponse | FailureResponse;

export type Request = {
  type: 'request',
  command: 'start-server' | 'stop-server',
  serverConfig: ThriftServerConfig,
};
export type ThriftServiceCommand = $PropertyType<Request, 'command'>;

export type SuccessResponse = {
  type: 'response',
  success: true,
  connectionOptions?: ConnectionOptions,
};

export type FailureResponse = {
  type: 'response',
  success: false,
  error: string,
};

export type ThriftMessage = {
  id: string,
  payload: ThriftMessagePayload,
};

export type ThrifClientSubscription = {unsubscribe: () => void};

export type ClientCloseCallBack = () => mixed;

export interface ThriftClient {
  getClient<T>(): T;
  close(): void;
  onClientClose(handler: ClientCloseCallBack): ThrifClientSubscription;
  onUnexpectedClientFailure(
    handler: ClientCloseCallBack,
  ): ThrifClientSubscription;
}

export interface ThriftServer {
  getConnectionOptions(): ConnectionOptions;
  close(): void;
}

export type ConnectionOptions =
  | {|
      port: number,
      useIPv4: boolean,
    |}
  | {|path: string|};
